package com.gitee.melin.bee.core.jdbc.dialect.mysql;

import com.gitee.melin.bee.core.jdbc.relational.ConnectionInfo;
import com.gitee.melin.bee.core.jdbc.enums.DataSourceType;
import com.gitee.melin.bee.core.jdbc.dialect.DataTypeConvertor;
import com.gitee.melin.bee.core.jdbc.dialect.AbstractJdbcDialect;
import com.gitee.melin.bee.core.jdbc.dialect.IDBQuery;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

public class MySqlJdbcDialect extends AbstractJdbcDialect {

    @Override
    public DataSourceType getDataSourceType() {
        return DataSourceType.MYSQL;
    }

    private static final Logger LOG = LoggerFactory.getLogger(MySqlJdbcDialect.class);

    public MySqlJdbcDialect(ConnectionInfo connectionInfo) {
        super(connectionInfo);
    }

    public MySqlJdbcDialect(Connection connection) {
        super(connection);
    }

    @Override
    protected IDBQuery getDBQuery() {
        return new MySqlQuery();
    }

    @Override
    protected DataTypeConvertor getTypeConvert() {
        return new MySqlTypeConvertor();
    }

    @Override
    protected void connectionProperties(Map<String, String> connectionProperties) {
        connectionProperties.put("useInformationSchema", "true");
        connectionProperties.put("useUnicode", "true");
        connectionProperties.put("characterEncoding", "utf8");
        connectionProperties.put("tinyInt1isBit", "false");
        connectionProperties.put("rewriteBatchedStatements", "true");
        connectionProperties.put("connectTimeout", "10000"); // 10s
    }

    @Override
    protected Driver getDriver() throws SQLException {
        return loadDriver(DataSourceType.MYSQL.getDriverClass());
    }

    @Override
    protected boolean filterSchema(String schemaName) {
        if (schemaName.equalsIgnoreCase("mysql")
                || schemaName.equalsIgnoreCase("sys")
                || schemaName.equalsIgnoreCase("performance_schema")
                || schemaName.equalsIgnoreCase("information_schema")) {
            return false;
        }
        return super.filterSchema(schemaName);
    }

    @Override
    public List<String> getDatabases() {
        return this.getSchemas();
    }

    @Override
    public List<String> listSchemas(Connection connection) {
        // for MySQL, we need to list catalogs instead of schemas
        try (ResultSet resultSet = connection.getMetaData().getCatalogs()) {
            List<String> schemaNames = Lists.newArrayList();
            while (resultSet.next()) {
                String schemaName = resultSet.getString("TABLE_CAT");
                // skip internal schemas
                if (filterSchema(schemaName)) {
                    schemaNames.add(schemaName);
                }
            }
            return schemaNames;
        }
        catch (SQLException e) {
            throw new RuntimeException("Get Scheme Error", e);
        }
    }

    @Override
    protected String getDDLColumnName() {
        return "Create Table";
    }

}
